package com.aspirecn.core.commons;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;

import com.aspire.core.match.ua.object.Device;
import com.aspire.core.match.ua.object.DeviceBrand;
import com.aspire.core.match.ua.object.DeviceGWUA;
import com.aspire.core.match.ua.object.DeviceKeyword;
import com.aspire.core.match.ua.object.DeviceUA;
import com.aspire.wap.core.http.RequestUtil;
import com.aspirecn.core.ShareCommon;
import com.aspirecn.core.datacache.useragent.*;
import com.aspirecn.core.object.MatchUACondition;

/**
 * UA适配搜索等通用方法
 * @author wangxinning
 *
 */
public class UserAgentUtils {

	//public final static Logger logger = Logger.getLogger(UserAgentUtils.class);
	public final static Logger logger_ua = Logger.getLogger("uamatchlog");
	
	private static DeviceKeywordCache deviceKeywordCache = ShareCommon.getInstance().getDeviceKeywordCache();
	private static DeviceBrandCache deviceBrandCache = ShareCommon.getInstance().getDeviceBrandCache();
	private static DeviceCache deviceCache = ShareCommon.getInstance().getDeviceCache();
	private static DeviceGWUACache deviceGWUACache = ShareCommon.getInstance().getDeviceGWUACache();
	private static DeviceOSCache deviceOSCache = ShareCommon.getInstance().getDeviceOSCache();
	private static DeviceUACache deviceUACache = ShareCommon.getInstance().getDeviceUACache();
	private static MMDeviceIDCache mmDeviceIDCache = ShareCommon.getInstance().getMMDeviceIDCache();
	
	/**
	 * 计算出多种关键词组合，从长到短适配，首先适配成功的算
	 * 
	 * 每次请求有缓存
	 * 
	 * @param args
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws InstantiationException 
	 * @throws IllegalAccessException 
	 */
	public static Device matchUA( String userAgentString ) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
		
		Device retDevice = null;
		
		//1.获取原始ua
		String ua = userAgentString;		
		if( StringUtils.isBlank(ua) )
		{
			return null;
		}
		
		//2013-09-05添加，优先适配逻辑
		String[] supreMatch = Configuration.getInstance().getUAMatchSuper();
		if( ArrayUtils.isNotEmpty(supreMatch) )
		{
			for( String s:supreMatch )
			{
				String k = StringUtils.substringBefore(s, "|");
				String id = StringUtils.substringAfter(s, "|");
				
				if( StringUtils.containsIgnoreCase(ua, k) && NumberUtils.isNumber(id) )
				{
					retDevice = deviceCache.getDevice(NumberUtils.toInt(id));
					if( retDevice != null )
					{
						retDevice.setDebugMatchArray(new String[]{StringUtils.lowerCase(k)});
						return retDevice;
					}
				}
			}
		}
		
		//String ua = "SAMSUNG-GT-S3370C/1.0 SHP/VPP/R5 Dolfin/1.5 Qtv/5.3 SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-N";
		//String ua = "HS-T30_TD/1.0 Release/06.28.2011 Threadx/4.0 Mocor/W10 Browser/NF4.0 Profile/MIDP-2.0 Config/CLDC-1.1";
		//String ua = "Nokia7230/5.0 (05.71) Profile/MIDP-2.1 Configuration/CLDC-1.1 Mozilla/5.0 AppleWebKit/420+ (KHTML, like Gecko) Safari/420+";
		//ua = "NokiaC5-03/22.0.007 (SymbianOS/9.4; U; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Safari/525 3gpp-gba";
		
		long start = System.currentTimeMillis();

		//2.初始化适配条件容器
		List<MatchUACondition> matchConditionList = new ArrayList<MatchUACondition>();
		
		//3.扫描关键字列表，填充条件容器
		//Iterator<DeviceKeyword> deviceKeywordIte = deviceKeywordCache.getDeviceKeywordList().iterator();
		//while( deviceKeywordIte.hasNext() )
		for( DeviceKeyword deviceKeyword:deviceKeywordCache.getDeviceKeywordList() )
		{
			//DeviceKeyword deviceKeyword = deviceKeywordIte.next();
			MatchUACondition baseMatchCondition = new MatchUACondition();
			
			//3.1.基础适配关键字
			baseMatchCondition.setDeviceid(deviceKeyword.getDevice_id());
			baseMatchCondition.addKeyword(deviceKeyword.getKeyword1());
			baseMatchCondition.addKeyword(deviceKeyword.getKeyword2());
			baseMatchCondition.addKeyword(deviceKeyword.getKeyword3());
			
			if( StringUtils.containsArrayIgnoreCase(ua, baseMatchCondition.getKeywords()) )
			{
				//3.2.加入仅包含关键字的条件到列表
				matchConditionList.add((MatchUACondition)BeanUtils.cloneBean(baseMatchCondition));
				
				//加入包含品牌英文的关键字
				//获取品牌
				Device device = deviceCache.getDevice(deviceKeyword.getDevice_id());
				if( device != null )
				{
					DeviceBrand brand = deviceBrandCache.getDeviceBrand(device.getBrand_id());
					if( brand != null )
					{
						MatchUACondition includeBrand = (MatchUACondition)BeanUtils.cloneBean(baseMatchCondition);
						includeBrand.addKeyword(brand.getEnglish_brand_name());
						matchConditionList.add(includeBrand);
						
						//System.out.println( matchConditionList.size() + ArrayUtils.toString(includeBrand.getKeywords()) );
					}
				}
				
				List<DeviceUA> deviceUAList = deviceUACache.getDeviceUA(deviceKeyword.getDevice_id());
				List<DeviceGWUA> deviceGWUAList = deviceGWUACache.getDeviceUA(deviceKeyword.getDevice_id());
				
				//3.3.排列组合其他条件
				if( !ObjectUtils.isEmptyList(deviceUAList) && !ObjectUtils.isEmptyList(deviceGWUAList) )
				{
					for( DeviceUA deviceUA:deviceUAList )
					{
						MatchUACondition matchCondition = (MatchUACondition)BeanUtils.cloneBean(baseMatchCondition);
						matchCondition.addKeyword(deviceUA.getDevice_os_ua());
						matchCondition.addKeyword(deviceUA.getDevice_ua());
						matchCondition.setOsua(deviceUA.getDevice_os_ua());
						matchCondition.setUa(deviceUA.getDevice_ua());
						for( DeviceGWUA deviceGWUA:deviceGWUAList )
						{
							MatchUACondition matchCondition2 = (MatchUACondition)BeanUtils.cloneBean(matchCondition);
							matchCondition2.addKeyword(deviceGWUA.getDevice_gw_ua());
							matchCondition2.setGwua(deviceGWUA.getDevice_gw_ua());
							matchConditionList.add(matchCondition2);
						}
					}
				}
				else if( !ObjectUtils.isEmptyList(deviceUAList) )
				{
					for( DeviceUA deviceUA:deviceUAList )
					{
						MatchUACondition matchCondition = (MatchUACondition)BeanUtils.cloneBean(baseMatchCondition);
						matchCondition.addKeyword(deviceUA.getDevice_os_ua());
						matchCondition.setOsua(deviceUA.getDevice_os_ua());
						matchCondition.addKeyword(deviceUA.getDevice_ua());
						matchCondition.setUa(deviceUA.getDevice_ua());
						matchConditionList.add(matchCondition);
					}
					
				}
				else if( !ObjectUtils.isEmptyList(deviceGWUAList) )
				{					
					for( DeviceGWUA deviceGWUA:deviceGWUAList )
					{
						MatchUACondition matchCondition = (MatchUACondition)BeanUtils.cloneBean(baseMatchCondition);
						matchCondition.addKeyword(deviceGWUA.getDevice_gw_ua());
						matchCondition.setGwua(deviceGWUA.getDevice_gw_ua());
						matchConditionList.add(matchCondition);
					}
				}
			}
		}
		
		//4.适配
		if( !ObjectUtils.isEmptyList(matchConditionList) )
		{	
			//排序
			Collections.sort(matchConditionList);
			for( MatchUACondition matchCondition:matchConditionList )
			{				
				
				if( StringUtils.containsArrayIgnoreCase(ua, matchCondition.getKeywords())
						&& 
						isProcessKeywords( ua, matchCondition.getKeywords() )					
						)
				{
					Device device = deviceCache.getDevice(matchCondition.getDeviceid());
					
					//适配成功
					if( device != null )
					{
						//判断是否是MM指定机型
						if( Configuration.getInstance().isMM() )
						{
							//不在MM机型库，继续下一个匹配
							if( !mmDeviceIDCache.isExist(device.getDevice_id()) )
							{
								continue;
							}
						}
						
						device.setDevice_os_ua(matchCondition.getOsua());
						device.setDevice_ua(matchCondition.getUa());
						device.setDeviceOS(deviceOSCache.getDeviceOS(device
								.getOs_id()));
						device.setDeviceBrand(deviceBrandCache
								.getDeviceBrand(device.getBrand_id()));
						device.setDebugMatchArray(matchCondition.getKeywords());
						
						retDevice = device;
						break;
					}
					
				}
			}
		}
		
		//根据字段做一次精确匹配
		if( retDevice == null )
		{
			retDevice = deviceCache.getDeviceByColume(userAgentString,
					new String[] { "device_name", "device_desc",
							"english_device_name", "english_device_desc" });
		}
		
		long end = System.currentTimeMillis();
		
		if( retDevice != null )
		{
			logger_ua.debug("useragent:" + ua + "###deviceid:"
					+ retDevice.getDevice_id() + "###os_ua:"
					+ retDevice.getDevice_os_ua() + "###ua:"
					+ retDevice.getDevice_ua() + "###times:" + (end - start) + "ms");
		}
		else
		{
			logger_ua.error("nomatch useragent:" + ua + "###times:" + (end - start) + "ms");
		}
		
		return retDevice;
	}	
	
	public static Device matchUA( HttpServletRequest request ) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
	{
		Device retDevice = (Device)request.getAttribute(Constant.REQUEST_ATTRIBUTE_KEY_DEVICE);
		if( retDevice != null )
		{
			return retDevice;
		}
		
		String ua = RequestUtil.getOriginalUserAgent(request);		
		retDevice = matchUA( ua );
		
		if( retDevice != null )
		{
			request.setAttribute(Constant.REQUEST_ATTRIBUTE_KEY_DEVICE, retDevice);
		}
		
		return retDevice;
	}
	
	
	/**
	 * 对于仅存在一个关键词的适配规则，是否处理
	 * @return
	 */
	private static boolean isProcessKeywords( String ua, String[] keywords )
	{		
		//关键字数量>1 或者 仅有一个的时候 长度》5
		if(ArrayUtils.getLength(keywords) > 1
				||
				StringUtils.length(keywords[0]) > 5)
		{
			return true;
		}
				
		//ucweb修改了ua休息，仅存在型号，所以可以
		//如：ucweb/2.0 (linux; u; adr 4.0.3; zh-cn; m032) u2/1.0.0 ucbrowser/9.2.3.324 u2/1.0.0 mobile
		String[] includekeywords = Configuration.getInstance().getUAMatchOneKeyword();
		
		if( ArrayUtils.isNotEmpty(includekeywords) )
		{
			for( String s:includekeywords )
			{
				if( StringUtils.containsIgnoreCase(ua, s) )
				{
					return true;
				}
			}
		}
		
		//可以添加很多其他的
		
		
		
		return false;
	}
	
	
	public static void main( String[] args ) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
	{
		String ua = "HS-T30_TD/1.0 Release/06.28.2011 Threadx/4.0 Mocor/W10 Browser/NF4.0 Profile/MIDP-2.0 Config/CLDC-1.1";
		System.out.println( UserAgentUtils.matchUA(ua) );
		
		
		
		//DeviceCache deviceCache = ShareCommon.getInstance().getDeviceCache();
		//deviceCache.getDevice(deviceid)
	}
}